package com.playball.lottery.eventmanger;

import java.util.Collection;


/**
 * <p>Handler 和Event 是多多对应的，但在程序中要求一个Handler 只对应一个事件</p>
 * <p>本程序模块使用事件管理者完成程序逻辑的处理过程。对于界面而言，所有的逻辑执行代码均在Frm 类中完成， 各个Frm
 * 只在创建时期存在联系（创建者不保存被创建者的引用），如果两个Frm要发生关系，必须通过EventManager 来实现相关的操作。
 * 即将针对界面编程转换为针对事件编程</p>
 * 
 * <p>事件响应处理的过程是同步的，只要事件发生，必须要等待该事件处理结束后才能继续向下执行，因此需要处理好何时报告事件。
 * 由于存在一个事件可以对应多个处理例程，但EventManager不能完成排序操作，因此对一个事件而言，处理例程之间具有无序性。
 * 如果必须对顺序做出要求，可以将单个事件拆成多个事件，按次序先后报告事件</p>
 * 
 * <p>如果需要知道一个事件A的操作结果，我们可以在报告A事件的对象内添加对B事件的处理例程，A事件执行完毕后，报告B事件。
 * 具体的数据信息可由参数传递。由于一个事件可以对应多个处理例程，因此不能使用onEvent的返回值和直接使用参数值接收处理
 * 结果。</p>
 * 
 * <p>事件是可以相互嵌套的，即响应一个事件的处理例程可以报告另一个事件。设存在ABC三个对象，A对象发生某中变化，报告事件1
 * 给B，B对象响应事件1做出相关处理，而相关处理中又包含向C对象报告事件2，这种情况即属于事件嵌套。尽管A的变化也引发了C对象的
 * 相关行为，但A对象只考虑自身相关的事件1的报告，对于其他的事件一概不问。这种机制有利于对象间的相互隐藏。</p>
 * 
 */
public class EventManager
{
	/**
	 * 
	 * 继承这个接口用来实现响应的处理例程
	 * 
	 */
	public interface EventHandler
	{
		public void excute(Object obj);
	}

	/**
	 * 获取一个Manager 实例
	 * 
	 * @return EventManager 实例
	 */
	public static EventManager getInstance()
	{
		if (null == m_istance)
		{
			m_istance = new EventManager();
		}

		return m_istance;
	}

	/**
	 * 清空全部的Handlers
	 */
	public void clearHandlers()
	{
		m_handlers.clear();
	}

	/**
	 * 注册事件的处理例程
	 * 
	 * @param event
	 *            事件类别
	 * 
	 * @param handler
	 *            处理例程
	 * 
	 * 
	 */
	public void registEventHandler(EventType event, EventHandler handler)
	{
		m_handlers.put(event, handler);

		String strTag = Opt_XHLLog.setTag("<<XHL-EventManager>>");
		Opt_XHLLog.out("Regist a event handler, event is: " + event.toString());
		Opt_XHLLog.setTag(strTag);
	}

	/**
	 * 
	 * @param handler
	 *            取消这个例程的注册
	 */
	public void unregistEventHandler(EventType event, EventHandler handler)
	{
		if (m_handlers.isEmpty())
		{
			return;
		}

		if (m_handlers.remove(event, handler))
		{
			Opt_XHLLog.out("There is a handler already regist, so we remove the last regist record");
		}
	}
	
	public void unregistEvent(EventType event)
	{
		if (m_handlers.isEmpty())
		{
			return;
		}
		
		m_handlers.remove(event);
	}
	
	/**
	 * 向EventManager 报告该事件
	 * 
	 * @param event
	 *            事件类别
	 * @param obj
	 *            参数
	 */
	public void onEvent(EventType event, Object obj)
	{
		if (m_handlers.isEmpty())
		{
			return;
		}

		Collection<EventHandler> handlers = m_handlers.get(event);

		if (null == handlers || handlers.isEmpty())
		{
			return;
		}

		for (EventHandler h : handlers)
		{
			if(EventType.EV_DAL_ONESECOND_TASK_COUNT_DOWN != event){
				String strTag = Opt_XHLLog.setTag("<<EventManager>>");
				Opt_XHLLog.out("Excute a event handler, event is: "+ event.toString());
				Opt_XHLLog.setTag(strTag);
			}
			h.excute(obj);
		}
	}

	private static EventManager m_istance = null;

	private MultiMap<EventType, EventHandler> m_handlers = new MultiMap<EventType, EventHandler>();

	private EventManager()
	{

	}
}
